package com.nulldev.util.dataManagement.preferencesAPI.legacy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Map;
import java.util.regex.Pattern;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.VariableAPI.BooleanUtil;
import com.nulldev.util.data.Variables;
import com.nulldev.util.data.Arrays.maps.FastMaps;
import com.nulldev.util.dataManagement.preferencesAPI.PreferenceInterface;
import com.nulldev.util.io.IOUtils;

public class LegacyAPIPreferences implements PreferenceInterface<String>, Serializable {

	private static final long serialVersionUID = -7085456817579848954L;
	private final transient Map<String, String> cache = FastMaps.map();
	private final File f;

	public LegacyAPIPreferences(final File f) {
		this.f = f;
		this.sync();
	}

	@Override
	public String get(String key) {
		return this.cache.get(key);
	}

	@Override
	public boolean has(String key) {
		Variables.notNullE(key);
		return this.cache.containsKey(key);
	}

	@Override
	public void set(String key, String value) {
		Variables.notNullE(key);
		if (key.isEmpty())
			throw new IllegalArgumentException("key is empty!");
		this.cache.put(key, value);
	}

	@Override
	public void sync() {
		try {
			if (this.f == null)
				return;
			if (this.cache.isEmpty()) {
				final FileReader fr = new FileReader(this.f);
				final BufferedReader br = new BufferedReader(fr);
				String line;
				while ((line = br.readLine()) != null) {
					final String[] s = line.split(Pattern.quote(": "));
					final String key = s[0];
					final String value = ArrayUtils.StringArrayUtils.addFrom(s, 1, ": ").replaceAll("<newline>", "\n");
					this.cache.put(key, value);
				}
				br.close();
			} else {
				final PrintWriter pw = new PrintWriter(this.f);
				for (final Map.Entry<String, String> entry : this.cache.entrySet()) {
					pw.print(entry.getKey());
					pw.print(": ");
					pw.print(entry.getValue().replaceAll("\n", "<newline>"));
				}
				pw.flush();
				pw.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean getAsBoolean(final String key) {
		return BooleanUtil.safeParse(get(key));
	}

	@Override
	public void reset() throws IOException {
		this.clear();
		if (this.f != null) {
			new PrintWriter(this.f).close();
		}
	}

	@Override
	public void clear() {
		this.cache.clear();
	}

	public static void main(String[] args) throws IOException {
		final File f = File.createTempFile("nullutil-prefs-test-", ".config");
		JVM.println("File: " + f);
		final LegacyAPIPreferences pref = new LegacyAPIPreferences(f);
		pref.set("test", "Hello world!");
		pref.set("other-value", "x");
		JVM.println("Syncing...");
		pref.sync();
		JVM.println("Written to file!");
		JVM.println("Reading...");
		pref.sync();
		JVM.println("Values:");
		JVM.println(pref.values());
		IOUtils.closeQuietly(pref);
	}

	private Map<String, String> values() {
		return this.cache;
	}

	@Override
	public Map<String, String> getAllOptions() {
		return this.cache;
	}

	@Override
	public void close() throws IOException {
		this.cache.clear();
	}
}
